package com.zsd.android.webrtcdemo;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.zsd.android.webrtcdemo.utils.MLog;

import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.Camera1Enumerator;
import org.webrtc.Camera2Enumerator;
import org.webrtc.CameraEnumerator;
import org.webrtc.CameraVideoCapturer;
import org.webrtc.DataChannel;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpReceiver;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements PeerConnection.Observer, View.OnClickListener {

    private EditText roomIdEt;
    private Button roomBtn;

    private final String[] permissions = {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE};
    private PeerConnection peerConnection;
    private EglBase.Context eglBaseContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        checkPermissions(permissions);
//        roomIdEt = findViewById(R.id.room_id_et);
        roomBtn = findViewById(R.id.room_btn);
        roomBtn.setOnClickListener(this);
    }

    private void initPeer() {
        // 第一步：初始化PeerConnectionFactory
        PeerConnectionFactory.InitializationOptions.Builder initializationOptionsBuilder = PeerConnectionFactory.InitializationOptions.builder(this);
        initializationOptionsBuilder.setEnableInternalTracer(true);
        PeerConnectionFactory.initialize(initializationOptionsBuilder.createInitializationOptions());
        // 第二步：创建PeerConnectionFactory
        PeerConnectionFactory.Builder peerConnectionFactoryBuilder = PeerConnectionFactory.builder();
        PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
        peerConnectionFactoryBuilder.setOptions(options);
        eglBaseContext = EglBase.create().getEglBaseContext();
        DefaultVideoDecoderFactory videoDecoderFactory = new DefaultVideoDecoderFactory(eglBaseContext);
        DefaultVideoEncoderFactory videoEncoderFactory = new DefaultVideoEncoderFactory(eglBaseContext, true, true);
        peerConnectionFactoryBuilder.setVideoDecoderFactory(videoDecoderFactory);
        peerConnectionFactoryBuilder.setVideoEncoderFactory(videoEncoderFactory);
        PeerConnectionFactory peerConnectionFactory = peerConnectionFactoryBuilder.createPeerConnectionFactory();
        // 第三步：
        // 创建VideoCapturer（视频捕捉器的一个顶级接口）
        // 它的的子接口为CameraVideoCapturer，封装了安卓相机的使用方法，使用它们可以轻松的获取设备相机数据，切换摄像头，获取摄像头数量等
        CameraVideoCapturer videoCapture = createVideoCapture(this);
        // 第四步：创建VideoSource/VideoTrack
        // VideoSource为视频源，通过核心类PeerConnectionFactory创建，
        // VideoTrack是对VideoSource的包装，可以方便的将视频源在本地进行播放，添加到MediaStream中进行网络传输。
        VideoSource videoSource = peerConnectionFactory.createVideoSource(true);
        VideoTrack videoTrack = peerConnectionFactory.createVideoTrack("videtrack", videoSource);
        // 第五步：创建AudioSource/AudioTrack
        // AudioSource/AudioTrack和上面的VideoSource/VideoTrack类似，
        // 从名字上面就知道是对音频的获取和处理了，AudioSource的创建很简单，直接用PeerConnectionFactory创建就可以了。
        // AudioSource 创建的时候需要传入MediaConstraints这个对象的实例，
        // 其用于对媒体的一些约束限制，创建的时候可以直接使用默认的。如果想自己定义，就需要自己填入相应的键值对了。
        MediaConstraints audioConstraints = new MediaConstraints();
        //回声消除
        audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googEchoCancellation", "true"));
        //自动增益
        audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googAutoGainControl", "false"));
        //高音过滤
        audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googHighpassFilter", "false"));
        //噪音处理
        audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googNoiseSuppression", "true"));
        AudioSource audioSource = peerConnectionFactory.createAudioSource(audioConstraints);
        AudioTrack audioTrack = peerConnectionFactory.createAudioTrack("audiotrack", audioSource);
        // 第六步：创建音频媒体流MediaStream
        // 音视频的媒体流，通过PeerConnectionFactory创建，
        // 用于PeerConnection通过网络传输发送给另一方。在媒体流传输之前，需要将前面获取的VideoTrack和AudioTrack添加进去。
        MediaStream mediaStream = peerConnectionFactory.createLocalMediaStream("localStream");
        mediaStream.addTrack(videoTrack);
        mediaStream.addTrack(audioTrack);
        // 第七部：创建PeerConnection
        // 用于p2p网络传输，双方信令的交换。webrtc是基于p2p的，因此在双方通信之前需要服务器帮助传递信令，
        // 并且需要添加STUN和TURN服务器网络穿透。在双方通道打开之后就可以将媒体流发送给另一方了。
        ArrayList<PeerConnection.IceServer> iceServers = new ArrayList<>();
        iceServers.add(PeerConnection.IceServer.builder("stun:stun2.l.google.com:19302").createIceServer());
        peerConnection = peerConnectionFactory.createPeerConnection(iceServers, this);
        peerConnection.addStream(mediaStream);
    }

    private CameraVideoCapturer createVideoCapture(Context mContext) {
        CameraEnumerator enumerator;
        if (Camera2Enumerator.isSupported(mContext)) {
            enumerator = new Camera2Enumerator(mContext);
        } else {
            enumerator = new Camera1Enumerator(true);
        }
        String[] deviceNames = enumerator.getDeviceNames();
        for (String deviceName : deviceNames) {
            if (enumerator.isFrontFacing(deviceName)) {
                CameraVideoCapturer capturer = enumerator.createCapturer(deviceName, null);
                if (capturer != null) {
                    return capturer;
                }
            }
        }
        for (String deviceName : deviceNames) {
            if (!enumerator.isFrontFacing(deviceName)) {
                CameraVideoCapturer capturer = enumerator.createCapturer(deviceName, null);
                if (capturer != null) {
                    return capturer;
                }
            }
        }
        return null;
    }

    private boolean checkPermissions(String[] permissions) {
        ArrayList<String> needPermissions = new ArrayList<>();
        for (String permission : permissions) {
            int checkSelfPermission = ContextCompat.checkSelfPermission(this, permission);
            if (PackageManager.PERMISSION_DENIED == checkSelfPermission) {
                needPermissions.add(permission);
            }
        }
        int size = needPermissions.size();
        if (size > 0) {
            ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[size]), 101);
            return false;
        }
        return true;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.room_btn:
                if (true) {
                    String trim = roomIdEt.getText().toString().trim();
                    MLog.i(trim);
                }
                if (!checkPermissions(permissions)) {
                    return;
                }
                String roomId = roomIdEt.getText().toString().trim();
                if (TextUtils.isEmpty(roomId)) {
                    return;
                }
                WebRTCManager.getInstance().connect(this, roomId);
                break;
        }
    }

    @Override
    public void onSignalingChange(PeerConnection.SignalingState signalingState) {

    }

    @Override
    public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {

    }

    @Override
    public void onIceConnectionReceivingChange(boolean b) {

    }

    @Override
    public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {

    }

    @Override
    public void onIceCandidate(IceCandidate iceCandidate) {

    }

    @Override
    public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {

    }

    @Override
    public void onAddStream(MediaStream mediaStream) {

    }

    @Override
    public void onRemoveStream(MediaStream mediaStream) {

    }

    @Override
    public void onDataChannel(DataChannel dataChannel) {

    }

    @Override
    public void onRenegotiationNeeded() {

    }

    @Override
    public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {

    }
}
